﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.Mvc;

namespace MvcImproved.Generic.Controls
{
	[ParseChildren(false)]
	[PersistChildren(true)]
	public class MemberSelector<TDataItem, TMemberValue> : NamedGenericControl<TDataItem, TMemberValue>, IDataItemContainer, IViewDataContainer<TMemberValue> where TMemberValue : class
	{
		public MemberSelector(Func<TDataItem, TMemberValue> valueMember)
			: base(valueMember)
		{}

		protected override void InitViewData()
		{
			if (_ViewData != null)
				return;

			base.InitViewData();

			_DataItem = (DataValue != null) ? ValueMemberLambda(DataValue) : null;
			_ViewData = new ViewDataDictionary<TMemberValue>(_DataItem);
		}

		public enum NullAction
		{
			Throw,
			SkipChildren,
			RenderDefault
		}

		public NullAction NullValueAction = NullAction.SkipChildren;

		ViewDataDictionary<TMemberValue> _ViewData;
		ViewDataDictionary<TMemberValue> IViewDataContainer<TMemberValue>.ViewData
		{
			get
			{
				if (_ViewData == null)
					InitViewData();
				return _ViewData;
			}
			set
			{
				_ViewData = value;
			}
		}

		ViewDataDictionary IViewDataContainer.ViewData
		{
			get
			{
				if (_ViewData == null)
					InitViewData();
				return _ViewData;
			}
			set
			{
				_ViewData = (ViewDataDictionary<TMemberValue>)value;
			}
		}

		
		TMemberValue _DataItem;
		public TMemberValue DataItem
		{
			get
			{
				if (_ViewData == null)
					InitViewData();
				return _DataItem;
			}
		}

		object IDataItemContainer.DataItem
		{
			get
			{
				if (_ViewData == null)
					InitViewData();
				return _DataItem;
			}
		}

		public int DataItemIndex
		{
			get
			{
				return 0;
			}
		}

		public int DisplayIndex
		{
			get
			{
				return 0;
			}
		}

		protected override void Render(HtmlTextWriter writer)
		{
			if (!DesignMode)
			{
				if (_DataItem == null)
				{
					if (NullValueAction == NullAction.SkipChildren)
						return;
					else if (NullValueAction == NullAction.Throw)
						throw new InvalidOperationException(String.Format("Expected non-null value for {0} in {1}", ValueMember, typeof(TDataItem)));
				}
			}

			base.Render(writer);
		}
	}

	// Non-generic version of the control that's used in the actual markup
	[ControlBuilder(typeof(GenericControlBuilder))]
	[GenericControlType(typeof(MemberSelector<,>), MemberValue = "ValueMember", GenericParameters = "ModelType")]
	[ParseChildren(false)]
	[PersistChildren(true)]
	public class MemberSelector : MemberSelector<object, object>
	{
		public MemberSelector()
			: base(null)
		{ }

		public string ModelType
		{
			get;
			set;
		}
	}
}
